using NuGet.Packaging;

using OpenIddict.Abstractions;

using static OpenIddict.Abstractions.OpenIddictConstants;


namespace DaprPlus.Identity.Api
{
    public class Worker(IServiceProvider rootProvider) : IHostedService
    {
        public async Task StartAsync(CancellationToken cancellationToken)
        {
            using var scope = rootProvider.CreateScope();
            var provider = scope.ServiceProvider;

            await CreateApplications(provider);

            await CreateScopes(provider);
        }

        private async Task CreateApplications(IServiceProvider provider)
        {
            var manager = provider.GetRequiredService<IOpenIddictApplicationManager>();

            var clientId = "VueApp.Admin";
            var desc = new OpenIddictApplicationDescriptor
            {
                ClientId = clientId,
                DisplayName = "Vue管理",
                ClientType = ClientTypes.Public,
                Permissions =
                {
                    Permissions.Endpoints.Token,
                    Permissions.Endpoints.Authorization,
                    Permissions.Endpoints.EndSession,
                    Permissions.GrantTypes.AuthorizationCode,
                    Permissions.GrantTypes.RefreshToken,
                    Permissions.ResponseTypes.Code,
                    Permissions.Scopes.Email,
                    Permissions.Scopes.Profile,
                    Permissions.Scopes.Roles,
                    Permissions.Prefixes.Scope + "identity_api",
                    Permissions.Prefixes.Scope + "todos_api",
                    Permissions.Prefixes.Scope + "softwares_api",
                    Permissions.Prefixes.Scope + "games_api",
                },
                Requirements =
                {
                    Requirements.Features.ProofKeyForCodeExchange
                },
                RedirectUris = { new Uri("http://localhost:5666/signin-oidc") },
                PostLogoutRedirectUris = { new Uri("http://localhost:5666/signout-oidc") }
            };
            var app = await manager.FindByClientIdAsync(clientId);
            if (app == null)
            {
                await manager.CreateAsync(desc);
            }
            else
            {
                await manager.UpdateAsync(app, desc);
            }

            clientId = "WpfApp.Client";
            desc = new OpenIddictApplicationDescriptor
            {
                ClientId = clientId,
                DisplayName = "WPF客户端",
                ClientType = ClientTypes.Public,
                Permissions =
                {
                    Permissions.Endpoints.Token,
                    Permissions.Endpoints.Authorization,
                    Permissions.Endpoints.EndSession,
                    Permissions.GrantTypes.AuthorizationCode,
                    Permissions.GrantTypes.RefreshToken,
                    Permissions.ResponseTypes.Code,
                    Permissions.Scopes.Email,
                    Permissions.Scopes.Profile,
                    Permissions.Scopes.Roles,
                    Permissions.Prefixes.Scope + "identity_api",
                    Permissions.Prefixes.Scope + "softwares_api",
                    Permissions.Prefixes.Scope + "games_api",
                },
                Requirements =
                {
                    Requirements.Features.ProofKeyForCodeExchange
                },
                RedirectUris = { new Uri("http://localhost:9066/signin-oidc") },
                PostLogoutRedirectUris = { new Uri("http://localhost:9066/signout-oidc") }
            };
            app = await manager.FindByClientIdAsync(clientId);
            if (app == null)
            {
                await manager.CreateAsync(desc);
            }
            else
            {
                await manager.UpdateAsync(app, desc);
            }

            clientId = "Apifox";
            desc = new OpenIddictApplicationDescriptor()
            {
                ClientId = clientId,
                ClientSecret = "984CAC06-C327-42E7-B68B-F8D2F908A4DC",
                DisplayName = clientId,
                ClientType = ClientTypes.Confidential,
                Permissions =
                {
                    Permissions.Endpoints.Token,
                    Permissions.Endpoints.Authorization,
                    Permissions.Endpoints.EndSession,
                    Permissions.GrantTypes.AuthorizationCode,
                    Permissions.GrantTypes.RefreshToken,
                    Permissions.ResponseTypes.Code,
                    Permissions.Scopes.Email,
                    Permissions.Scopes.Profile,
                    Permissions.Scopes.Roles,
                    Permissions.Prefixes.Scope + "identity_api",
                    Permissions.Prefixes.Scope + "todos_api",
                    Permissions.Prefixes.Scope + "softwares_api",
                    Permissions.Prefixes.Scope + "games_api",
                },
                RedirectUris = { new Uri("http://localhost:8080/callback") },
            };
            app = await manager.FindByClientIdAsync(clientId);
            if (app == null)
            {
                await manager.CreateAsync(desc);
            }
            else
            {
                await manager.UpdateAsync(app, desc);
            }

            var clients = new[]
            {
                new { ClientId = "Identity.Service", ClientSecret = "B4939BE1-17FF-49E0-9D01-03A13EDEA3BA", DisplayName = "认证服务" },
                new { ClientId = "Todos.Service", ClientSecret = "83144118-C359-41D7-95BC-459CB31DA993", DisplayName = "待办服务" },
                new { ClientId = "Softwares.Service", ClientSecret = "A925A962-521F-4A8F-A22D-672D96FB9E07", DisplayName = "软件服务" },
                new { ClientId = "Games.Service", ClientSecret = "FD688983-E338-4DE2-B8DE-114F753A192E", DisplayName = "游戏服务" },
            };

            foreach (var client in clients)
            {
                desc = new OpenIddictApplicationDescriptor()
                {
                    ClientId = client.ClientId,
                    ClientSecret = client.ClientSecret,
                    DisplayName = client.DisplayName,
                    ClientType = ClientTypes.Confidential,
                    Permissions =
                    {
                        Permissions.Endpoints.Introspection
                    }
                };
                app = await manager.FindByClientIdAsync(client.ClientId);
                if (app == null)
                {
                    await manager.CreateAsync(desc);
                }
                else
                {
                    await manager.UpdateAsync(app, desc);
                }
            }
        }

        private async Task CreateScopes(IServiceProvider provider)
        {
            var manager = provider.GetRequiredService<IOpenIddictScopeManager>();

            var scopes = new[]
            {
                new { Name = "identity_api", DisplayName = "认证服务API", Resource = new[] { "Identity.Service" } },
                new { Name = "todos_api", DisplayName = "待办服务API", Resource = new[] { "Todos.Service" } },
                new { Name = "softwares_api", DisplayName = "软件服务API", Resource = new[] { "Softwares.Service" } },
                new { Name = "games_api", DisplayName = "游戏服务API", Resource = new[] { "Games.Service" } },
            };

            foreach (var scope in scopes)
            {
                var desc = new OpenIddictScopeDescriptor()
                {
                    Name = scope.Name,
                    DisplayName = scope.DisplayName
                };
                    desc.Resources.AddRange(scope.Resource);
                var sp = await manager.FindByNameAsync(scope.Name);
                if (sp == null)
                {
                    await manager.CreateAsync(desc);
                }
                else
                {
                    await manager.UpdateAsync(sp, desc);
                }
            }
        }

        public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
    }
}
